package com.ltv.xiangqibook.web;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.ocpsoft.pretty.time.PrettyTime;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Text;


@SuppressWarnings("serial")
public class XiangQiGameServlet extends HttpServlet {
	public static final int PAGE_SIZE = 10;
	public static final int PAGE_NUM = 10;
	
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");
        
        
        String language = request.getParameter("language");
        
        if (language != null) {
            request.getSession(true).setAttribute("language", language);
        } else {
        	language = (String) request.getSession(true).getAttribute("language");
            if (language == null) {
            	// Default language is vietnamese
            	language = "vi";
            }
        }
        
        
        String game_id = request.getParameter("game_id");
        
        if (game_id == null) {
            game_id = (String) request.getSession(true).getAttribute("game_id");
        }
        
        if (game_id == null) {
            return;
        }
        
        HttpSession session = request.getSession(true);
        session.setAttribute("game_id", game_id);
        
		Entity game = Game.getGame(game_id);
		
		Map<String, Object> gameVO = game.getProperties();
		String gameLocation = (String) gameVO.get("location");
		String comment = ((Text) gameVO.get("comment")).getValue();
        
      // set value for attribute game_location_base: the location without html file name
      String gameLocationBase = "/";
      String elements[] = gameLocation.split("/");
      for (int i = 1; i < elements.length - 2; i++) {
          gameLocationBase += elements[i] + "/";
      }
      
      if (elements.length - 2 >= 0) {
          gameLocationBase += elements[elements.length - 2];
      }
      
      session.setAttribute("game_location_base", gameLocationBase);
        
        PrintWriter out = response.getWriter();
        
        if (gameLocation.endsWith(".html")) {
	        out.println(
                    "<HTML>" +
                    "<HEAD>" +
                    "<link rel=\"stylesheet\" type=\"text/css\" href=\"css/xiangqibook.css\" />" +
                    "<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js\" type=\"text/javascript\"></script>" +
                    "</HEAD>" +
                    "<BODY>"
                    );
	        
	        // Write html file
	        File htmlFile = new File("views/" + game_id + ".html");
	        if (htmlFile.exists()) {
	        	try {
					writeHtmlFile(htmlFile, response);
				} catch (Exception e) {
					e.printStackTrace();
				}
	        }
	        
	        out.println("<h2>" + MessageService.getInstance().getMessage("comment", language) + "</h2>");
	        out.println("<hr>");
	        
	        Query query = new Query("posts");
	        query.addFilter("game_id", FilterOperator.EQUAL, game_id);
	        
			PreparedQuery queryString = Util.getDatastoreServiceInstance().prepare(query);
		    
		    int rowCount = queryString.countEntities();
		    
		    // set offset for the results to be fetched
		    String page = request.getParameter("page");
		    int offset = 0;
	    	try {
	    		offset = Integer.parseInt(page)*PAGE_SIZE;
	    	} catch (Exception e) {
	    		offset = 0;
	    	}
	    	
	        // fetch results from datastore based on offset and page size
	        FetchOptions fetchOptions = FetchOptions.Builder.withLimit(PAGE_SIZE);
	
	        Iterable<Entity> posts = queryString
	            .asIterable(fetchOptions.offset(offset));
	    	
	        float pageCount = (float) rowCount / PAGE_SIZE;
	        if (pageCount > rowCount / PAGE_SIZE)
	          pageCount = (int) pageCount + 1;
	        else
	          pageCount = (int) pageCount;
	        
			if (rowCount > PAGE_SIZE) {
				if (pageCount <= PAGE_NUM) {
		        	for (int i = 1; i<= pageCount; i++) {
		        		if (offset/PAGE_SIZE + 1 == i) {
		        			out.println(i);
		        		} else {
		        			out.println("<a href=\"XiangQiGame?page=" + (i-1) + "\">" + i + "</a>");
		        		}
		        	}
		        } else {
		        	int pageCountInt = (int)pageCount;
		        	int currentPage = offset/PAGE_SIZE;
		        	int startPage = Math.max(0, currentPage - PAGE_NUM/2);
		        	int endPage = Math.min(pageCountInt - 1, startPage + PAGE_NUM - 1);
		        	
		        	for (int i = startPage; i <= endPage; i++) {
		        		if (offset/PAGE_SIZE == i) {
		        			out.println(i+1);
		        		} else {
		        			out.println("<a href=\"XiangQiGame?page=" + i + "\">" + (i+1) + "</a>");
		        		}
		        	}
		        }
			}
	        
			if (posts != null) {
				writePosts(posts, response, language);
			}
			
			if (rowCount > PAGE_SIZE) {
				if (pageCount <= PAGE_NUM) {
		        	for (int i = 1; i<= pageCount; i++) {
		        		if (offset/PAGE_SIZE + 1 == i) {
		        			out.println(i);
		        		} else {
		        			out.println("<a href=\"XiangQiGame?page=" + (i-1) + "\">" + i + "</a>");
		        		}
		        	}
		        } else {
		        	int pageCountInt = (int)pageCount;
		        	int currentPage = offset/PAGE_SIZE;
		        	int startPage = Math.max(0, currentPage - PAGE_NUM/2);
		        	int endPage = Math.min(pageCountInt - 1, startPage + PAGE_NUM - 1);
		        	
		        	for (int i = startPage; i <= endPage; i++) {
		        		if (offset/PAGE_SIZE == i) {
		        			out.println(i+1);
		        		} else {
		        			out.println("<a href=\"XiangQiGame?page=" + i + "\">" + (i+1) + "</a>");
		        		}
		        	}
		        }
			}
	        
	        writePostForm(response, language, "postForm", "XiangQiPost", game_id);
	        
	        out.println("</BODY>\n" + "</HTML>");
        }
        
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
    
    private void writePosts(Iterable<Entity> posts, HttpServletResponse resp, String language) throws IOException {
    	PrintWriter out = resp.getWriter();
    	
    	out.println("<script>");
    	out.println("    String.prototype.trim = function() {");
    	out.println("        return this.replace(/^\\s+|\\s+$/g,\"\");");
    	out.println("    }");
    	out.println("</script>");
    	
    	boolean odd = true;
    	out.println("<table class=\"list\" width=\"100%\">");
    	for (Entity post : posts) {
    		Map<String, Object> postVO = post.getProperties();
    		String content = ((Text) postVO.get("content")).getValue();
    		String author = (String) postVO.get("author");
    		Date created_time = (Date) postVO.get("created_time");
    		
    		if (odd) {
    			out.println("<tr class=\"odd\">");
    		} else {
    			out.println("<tr class=\"even\">");
    		}
    		out.println("<td>");
			
			out.println("<pre class=\"pre\">");
			out.println(content);
			out.println("</pre>");
			
			if (author != null && !author.equals("")) {
				out.println("<label class=\"author\">");
				out.println(author);
				out.println("</label>");
				
				out.println("<label class=\"sep\">");
				out.println("&nbsp;|&nbsp;");
				out.println("</label>");
			}
			
			if (created_time != null) {
				PrettyTime t = new PrettyTime();
				out.println("<label class=\"time_ago\">");
				out.println(t.format(created_time));
				out.println("</label>");
			}
			
			Query query = new Query("answers");
	        query.addFilter("post_id", FilterOperator.EQUAL, post.getKey().getId());
	        
	        PreparedQuery queryString = Util.getDatastoreServiceInstance().prepare(query);
	        
	        Iterable<Entity> answers = Answer.getAllanswersByPostId(Long.toString(post.getKey().getId()));
	        
	        for (Entity answer : answers) {
	    		Map<String, Object> answerVO = answer.getProperties();
	    		String answer_content = ((Text) answerVO.get("content")).getValue();
	    		String answer_author = (String) answerVO.get("author");
	    		Date answer_created_time = (Date) answerVO.get("created_time");
	    		
	    		out.println("<br />");
	    		
	    		out.println("<pre class=\"pre\">");
				out.println(answer_content);
				out.println("</pre>");
				
				if (answer_author != null && !answer_author.equals("")) {
					out.println("<label class=\"author\">");
					out.println(answer_author);
					out.println("</label>");
					
					out.println("<label class=\"sep\">");
					out.println("&nbsp;|&nbsp;");
					out.println("</label>");
				}
				
				if (answer_created_time != null) {
					PrettyTime t = new PrettyTime();
					out.println("<label class=\"time_ago\">");
					out.println(t.format(answer_created_time));
					out.println("</label>");
				}
	        }
	        
			out.println("<br />");
			out.println("<br />");
			
			out.println("<button id=\"" + post.getKey().getId() + "_expanderHead\"><span style=\"color:blue\" id=\"" + post.getKey().getId() + "_expanderSign\">"
					+ MessageService.getInstance().getMessage("comment.reply", language)
					+ "</span></button><div id=\"" + post.getKey().getId() + "_expanderContent\" style=\"display:none\">");
			writePostForm(resp, language, "answerForm" + post.getKey().getId(), "XiangQiAnswer", Long.toString(post.getKey().getId()));
			out.println("</div><script type=\"text/javascript\">");
			out.println("$(document).ready(function(){");
			out.println(" $(\"#" + post.getKey().getId() + "_expanderHead\").click(function(){");
			out.println("        $(\"#" + post.getKey().getId() + "_expanderContent\").slideToggle();");
			out.println("    });");
			out.println("});");
			out.println("</script>");
			
			out.println("</td>");
			out.println("</tr>");
    		
    		odd = !odd;
    	}
    	out.println("</table>");
    }
    
    private void writePostForm(HttpServletResponse resp, String language, String formName, String action, String id) throws IOException {
    	PrintWriter out = resp.getWriter();
    	
    	out.println("<script>");
    	out.println("    function " + "postComment_" + formName + "() {");
    	String author_error_msg = "author_error_msg_" + formName;
    	String comment_error_msg = "comment_error_msg_" + formName;
    	out.println("        document.getElementById('" + author_error_msg + "').innerHTML = '';");
        out.println("        document.getElementById('" + comment_error_msg + "').innerHTML = '';");
        
    	out.println("        var ret = true;");
    	
    	out.println("        var author = document.forms[\"" + formName + "\"][\"author\"].value;");
    	out.println("        var comment = document.forms[\"" + formName + "\"][\"comment\"].value;");
    	
    	out.println("        if (author == null || author.trim() == \"\") {");
    	out.println("            ret = false;");
    	out.println("            document.getElementById('" + author_error_msg + "').innerHTML = '<font color=\"red\">" +
    								MessageService.getInstance().getMessage("comment.author.required", language) + "</font>';");
    	out.println("        }");
    	
    	out.println("        if (comment == null || comment.trim() == \"\") {");
    	out.println("            ret = false;");
    	out.println("            document.getElementById('" + comment_error_msg + "').innerHTML = '<font color=\"red\">" +
    								MessageService.getInstance().getMessage("comment.comment.required", language) + "</font>';");
    	out.println("        }");
    	out.println("        if (ret) {");
    	out.println("            document.forms[\"" + formName + "\"][\"sButton\"].disabled = true;");
    	out.println("        }");
    	out.println("        return ret;");
    	out.println("    }");
    	
    	// JSObject
//    	out.println("    function exportHTML(text) {");
//    	out.println("        myWindow=window.open('','','width=1000,height=600');");
//    	out.println("        myWindow.document.write('<textarea style=\"width:100%;height:100%\"  wrap=\"off\">' + text + '</textarea>');");
//    	out.println("        myWindow.focus();");
//    	out.println("    }");
    	
    	out.println("</script>");

    	out.println("<form name=\"" + formName + "\" method=\"post\" action=\"" + action + "\" onsubmit=\"return postComment_" + formName + "()\">");
    	out.println("    <br>");
    	out.println("    <label>" + MessageService.getInstance().getMessage("comment.author.label", language) + "</label>");
    	out.println("    <br>");
    	out.println("    <div id=\"author_error_msg_" + formName + "\"></div>");
        out.println("    <input style=\"width:100%\" type=\"text\" name=\"author\" maxlength=\"100\" />");
        out.println("    <br>");
        out.println("    <label>" + MessageService.getInstance().getMessage("comment.comment.label", language) + "</label>");
        out.println("    <br>");
        out.println("    <div id=\"comment_error_msg_" + formName + "\"></div>");
    	out.println("    <textarea style=\"width:100%\" name=\"comment\" rows=\"10\" maxlength=\"4000\"></textarea>");
    	out.println("    <br>");
    	out.println("    <input style=\"width:100%\" type=\"hidden\" name=\"id\" value=\"" + id + "\" maxlength=\"100\" />");
    	out.println("    <br>");
    	out.println("    <input type=\"submit\" value=\"" + MessageService.getInstance().getMessage("comment.submit.button", language) + "\" name=\"sButton\"/>");
    	out.println("</form>");
    }
    
    private void writeHtmlFile(File htmlFile, HttpServletResponse resp) throws Exception {
    	PrintWriter out = resp.getWriter();
    	FileInputStream in = null;
    	BufferedReader fileReader = null;
    	String line = null;
    	try {
    		fileReader = new BufferedReader(
                    new InputStreamReader(new FileInputStream(htmlFile), "utf-8"));
    		line = fileReader.readLine();
    		
    		while (line != null) {
    			out.println(line);
    			line = fileReader.readLine();
    		}
			
		} finally {
			if (in != null) {
				in.close();
			}
			if (fileReader != null) {
				fileReader.close();
			}
		}
    }
    
}
